package com.ruoyi.boat.utils;

import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

@Slf4j
public class ByteUtil {

    /**
     * 字节转十六进制
     *
     * @param b 需要进行转换的byte字节
     * @return 转换后的Hex字符串
     */
    public static String byteToHex(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() < 2) {
            hex = "0" + hex;
        }
        return hex.toUpperCase();
    }

    /**
     * 字节数组转16进制
     *
     * @param bytes 需要转换的byte数组
     * @return 转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        return bytesToHex(bytes, null);
    }

    public static String bytesToHex(byte[] bytes, String sep) {
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes) {
            String hex = Integer.toHexString(aByte & 0xFF);
            if (hex.length() < 2) {
                sb.append(0);
            }
            sb.append(hex.toUpperCase());
            if (!Objects.isNull(sep)) sb.append(sep);
        }
        int splitLength = !Objects.isNull(sep) ? sep.length() : 0;
        return sb.substring(0, sb.length() - splitLength).toUpperCase();
    }

    /**
     * Hex字符串转byte
     *
     * @param inHex 待转换的Hex字符串
     * @return 转换后的byte
     */
    public static byte hexToByte(String inHex) {
        return (byte) Integer.parseInt(inHex, 16);
    }

    /**
     * hex字符串转byte数组
     *
     * @param inHex 待转换的Hex字符串
     * @return 转换后的byte数组结果
     */
    public static byte[] hexToByteArray(String inHex) {
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1) {
            //奇数
            hexlen++;
            result = new byte[(hexlen / 2)];
            inHex = "0" + inHex;
        } else {
            //偶数
            result = new byte[(hexlen / 2)];
        }
        int j = 0;
        for (int i = 0; i < hexlen; i += 2) {
            result[j] = hexToByte(inHex.substring(i, i + 2));
            j++;
        }
        return result;
    }

    public static String byteToBcdString(byte[] bytes) {
        StringBuilder hexToStr = new StringBuilder();

        for (byte b : bytes) {
            String temp = Integer.toHexString(b & 0xff);
            hexToStr.append(temp.length() == 2 ? temp : "0" + temp);
        }
        return hexToStr.toString();
    }

    public static String bcd2Str(byte[] bytes) {
        StringBuilder temp = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
            temp.append((byte) (bytes[i] & 0x0f));
        }
        return temp.substring(0, 1).equalsIgnoreCase("0") ? temp.substring(1) : temp.toString();
    }

    /**
     * 合并byte[]数组 （不改变原数组）
     *
     * @param byte_1
     * @param byte_2
     * @return 合并后的数组
     */
    public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
        byte[] byte_3 = new byte[byte_1.length + byte_2.length];
        System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
        System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
        return byte_3;
    }

    /**
     * 截取byte数组   不改变原数组
     *
     * @param b      原数组
     * @param off    偏差值（索引）
     * @param length 长度
     * @return 截取后的数组
     */
    public static byte[] subByte(byte[] b, int off, int length) {
        byte[] b1 = new byte[length];
        System.arraycopy(b, off, b1, 0, length);
        return b1;
    }

    //高位在前 低位在后
    //java中没有无符号整形，4个字节数组转的时候需要先化为long
    public static long bytesToLong(byte[] bytes) {
        String hexStr = bytesToHex(bytes, "");
        return Long.parseLong(hexStr, 16);
    }

    //四个字节转换为带符号的int
    public static int bytesToInt(byte[] bytes) {
        int result = 0;
        for (int i = 0; i < bytes.length; i++) {
            result |= (bytes[i] & 0xff) << (bytes.length - 1 - i) * 8;
        }
        return result;
    }

    //CRC16-CCITT 校验
    public static String calculateCRC16(byte[] bytes) {
        int crc = 0x0000; // initial value
        int polynomial = 0x8408;// poly value reversed 0x1021;

        int i, j;
        for (i = 0; i < bytes.length; i++) {
            crc ^= ((int) bytes[i] & 0x000000ff);
            for (j = 0; j < 8; j++) {
                if ((crc & 0x00000001) != 0) {
                    crc >>= 1;
                    crc ^= polynomial;
                } else {
                    crc >>= 1;
                }
            }
        }
        return StringUtils.leftPad(Integer.toHexString(crc & 0xFFFF), 4, '0');
    }

    public static byte[] hexStrToBytes(String hexStr) {
        hexStr = hexStr.toUpperCase();
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            result[i] = (byte) Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16);
        }
        return result;
    }

    public static byte[] intToBytes(int number, int length) {
        byte[] result = new byte[length];
        for (int i = 0; i < length; i++) {
            result[i] = (byte) ((number >> ((length - 1 - i) * 8)) & 0xff);
        }
        return result;
    }

    public static byte[] combineBytes(byte[]... bytesList) {
        int count = 0;
        for (int i = 0; i < bytesList.length; i++) {
            count += bytesList[i].length;
        }
        byte[] result = new byte[count];
        int index = 0;
        for (int i = 0; i < bytesList.length; i++) {
            byte[] temp = bytesList[i];
            for (int j = 0; j < temp.length; j++) {
                result[index + j] = temp[j];
            }
            index += temp.length;
        }
        return result;
    }

    public static byte xorCheck(byte[] beCheck) {
        byte result = 0x00;
        for (int i = 0; i < beCheck.length; i++) {
            result ^= beCheck[i];
        }
        return result;
    }
}
